
#ifndef __Game_h_
#define __Game_h_

#define OIS_DYNAMIC_LIB
#include "BaseApplication.h"
#include "IMoveManager.h"
#include "MoveFactory.h"
#include "ControlStatus.h"
#include "ControlContext.h"
#include "EntityControl.h"
#include "PhysicsEntity.h"

#include "ContactReport.h"

#include "PlayerControlElement.h"
#include "PlayerController.h"
#include "PlayerControlLogic.h"

#include "Target.h"
#include "TargetController.h"
#include "TargetControlLogic.h"
#include "Launcher.h"

#include "Trigger.h"
#include "DamageAction.h"
#include "PositionReq.h"
#include "RoundCamera.h"
#include "KilledReq.h"
#include "GameOverAction.h"
#include "ExplodeAction.h"

#include "PSysFromScript.h"

#include "stdafx.h"

// Something for collision reaction
//extern ContactAddedCallback gContactAddedCallback;

class Game : public BaseApplication
{
	RoundCamera *rCamera;
	Move::IMoveManager* move;

	lua_State *LuaState;


	Ogre::TexturePtr camImage;
	//MyGUI::StaticImagePtr image;

	CEGUI::OgreRenderer* mRenderer;

	//OgreBulletDynamics::DynamicsWorld *mWorld;	// OgreBullet World
	//OgreBulletCollisions::DebugDrawer *debugDrawer;
	//int mNumEntitiesInstanced;

	//std::deque<OgreBulletDynamics::RigidBody *>         mBodies;
	//std::deque<OgreBulletCollisions::CollisionShape *>  mShapes;
	//Ogre::Vector3 gravityVector;
	//Ogre::AxisAlignedBox bounds;


	// PhysX specific parts
	NxScene* mNxScene;
	bool inited;
	NxPhysicsSDK* mPhysicsSDK;

	ControlStatus controlStatus;
	Ogre::SceneManager* controlSceneManager;
	//std::map<Ogre::String, ControlLogic*, Ogre::String::compare<Ogre::String>> controlLogics;
	std::map<std::string, ControlLogic*> controlLogics;
	std::map<std::string, NxActorDesc*> actorDescMap;

	//Ogre::Entity * moveTest;


public:
	Game(void);
	virtual ~Game(void);

protected:
	virtual void createScene(void);
	virtual void createFrameListener(void);
	virtual void destroyScene(void);
	virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);
	virtual bool configure();
	bool initMove();
	//binds the move to ControlStatus
	void initControlStatus();
	//Initializing PhysX
	void initPhysX();

	// You may remove the comment, if you want to test with PS Move only
	//virtual bool keyPressed( const OIS::KeyEvent &arg );
	// You may remove the comment, if you want to test with PS Move only
	//virtual bool keyReleased( const OIS::KeyEvent &arg );
	virtual bool mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id );
	virtual bool mouseMoved( const OIS::MouseEvent &arg );
	virtual void processUnbufferedKeyInput(const Ogre::FrameEvent& evt);
	bool frameStarted(const Ogre::FrameEvent& evt);
	bool frameEnded(const Ogre::FrameEvent& evt);
	void copyCameraImageToTexture(Ogre::TexturePtr texture);
	virtual void setupLuabindings();

	virtual void runScript(std::string luaFile);

	bool quit(const CEGUI::EventArgs &e);
	void setupCollisions();


	//functions for Luabind

	void SetAmbientLightColor(float r,float g, float b);
	void createSceneNode(luabind::object pos,luabind::object ori,luabind::object scale,luabind::object initializer);
	void addSceneNode(Ogre::SceneNode *node,Ogre::SceneNode *controlnode,luabind::object pos,luabind::object ori,luabind::object scale,luabind::object initializer);
	void addStaticEntity(Ogre::SceneNode *node,luabind::object param); 

	void addTrigger(EntityControl *ent,luabind::object initializer);
	void createDamageAction(Trigger *tr, luabind::object param);
	void createPositionReq(Trigger *tr, luabind::object param);
	void addTargetControlLogic(std::string name, luabind::object param, luabind::object initializer);
	void addTarget(TargetControlLogic* targetControlLogic,luabind::object param);
	void addProjectileTarget(TargetControlLogic* targetControlLogic,luabind::object param);
	void addPhysicsEntity(const Ogre::String &entityName, Ogre::SceneNode* node, Ogre::SceneNode* controlNode, luabind::object param,luabind::object initializer);
	void addPhysicsTerrain(const Ogre::String &entityName, Ogre::SceneNode* node, Ogre::SceneNode* controlNode, luabind::object param);
	void setCamera(Ogre::SceneNode* node);
	void addLauncher(TargetControlLogic* targetControlLogic, luabind::object param);
	void addProjectile(const Ogre::String modelMeshName, Ogre::Vector3 velocity,
		Ogre::SceneNode* node, Ogre::SceneNode* controlNode, std::string controlLogicName);
	void SetRoundCamera(luabind::object param);
	void createGameOverAction(Trigger *tr);
	void createKilledReq(Trigger *tr);
	void createExplodeAction(Trigger *tr);
	void createCamera(Ogre::SceneNode* node,luabind::object param);
	void createPSysAction(Trigger *tr, luabind::object param);
	void createActorDesc(luabind::object param,luabind::object initializer);
	void addBoxShapeDesc(NxActorDesc *actorDesc,luabind::object param);

private:
	void control(Ogre::Real);
	void nodeControl(const ControlContext&, Ogre::SceneNode*);
	//Function for creating an entity
	
};

// Contact happened callback
//static bool myContactAddedCallback(
//	btManifoldPoint& cp,
//	const btCollisionObject* colObj0, int partId0, int index0, 
//	const btCollisionObject* colObj1, int partId1, int index1);


#endif // #ifndef __Game_h_
